package dal

import (
	"database/sql"
	"fmt"
	"scheduler/util"
	"time"

	log "github.com/omidnikta/logrus"
)

const (
	TBL_JOBS = "jobs"
)

type jobModel struct{}

var _jobModel = &jobModel{}

func JobModel() *jobModel {
	return _jobModel
}

func (j *jobModel) Insert(data *Job) (*Job, error) {
	jobID := util.JobID(data.Target, data.Kind)
	sqlStr := fmt.Sprintf("INSERT %s SET id='%s',created_at=%d", TBL_JOBS, jobID, time.Now().Unix())
	trans, err := db.Begin()
	if nil != err {
		log.Errorln(err)
		return nil, err
	}
	_, err = trans.Exec(sqlStr)
	if nil != err {
		log.Errorln(err, sqlStr)
		trans.Rollback()
		return nil, err
	}

	for _, t := range data.Tasks {
		taskID := util.UUID()
		sqlStr2 := fmt.Sprintf("INSERT %s SET id='%s',created_at=%d,job_id='%s',addr='%s',path='%s',start_at=%d", TBL_TASKS, taskID, time.Now().Unix(), jobID, t.Addr, t.Path, t.StartAt)

		_, err = trans.Exec(sqlStr2)
		if nil != err {
			log.Errorln(err, sqlStr2)
			trans.Rollback()
			return nil, err
		}
	}

	err = trans.Commit()
	if nil != err {
		log.Errorln(err)
		trans.Rollback()
		return nil, err
	}

	//TODO
	var job Job
	job.ID = jobID
	return &job, nil
}

func (j *jobModel) Get(id string) (*Job, error) {
	tasks, err := TaskModel().Get(id)
	if nil != err {
		log.Errorln(err)
		return nil, err
	}

	job := Job{}
	job.ID = id
	job.Tasks = tasks

	return &job, nil
}

//func (j *jobModel) doGet(id string) (*Job, error) {
//	sqlStr := fmt.Sprintf("SELECT id FROM %s", TBL_JOBS)
//	row, err := db.QueryRow(sqlStr)
//	if nil != err {
//		if sql.ErrNoRows == err {
//			log.Warnf(sqlStr, sql.ErrNoRows)
//			return jobs, nil
//		}

//		log.Errorln(err)
//		return nil, err
//	}

//	var job Job
//	err = row.Scan(&job.ID)
//	if nil != err {
//		log.Errorln(err)
//		return nil, err
//	}

//	return &job, nil
//}

func (t *jobModel) GetAll() ([]*Job, error) {
	jobs, err := t.doGetAll()
	if nil != err {
		log.Errorln(err)
		return nil, err
	}

	for _, j := range jobs {
		tasks, err := TaskModel().Get(j.ID)
		if nil != err {
			log.Errorln(err)
			return nil, err
		}
		j.Tasks = tasks
	}

	return jobs, nil
}

func (t *jobModel) doGetAll() ([]*Job, error) {
	jobs := []*Job{}
	sqlStr := fmt.Sprintf("SELECT id FROM %s", TBL_JOBS)
	rows, err := db.Query(sqlStr)
	if nil != err {
		if sql.ErrNoRows == err {
			log.Warnf(sqlStr, sql.ErrNoRows)
			return jobs, nil
		}

		log.Errorln(err)
		return nil, err
	}

	for rows.Next() {
		var job Job
		err = rows.Scan(&job.ID)
		if nil != err {
			log.Errorln(err)
			return nil, err
		}
		jobs = append(jobs, &job)
	}

	return jobs, nil
}
